<?php

/**
 * 模型基类
 * 
 * 该类不继承任何类,且在该类方法中只能返回数据,不能输出任何数据
 * 同时该类不可以使用$this->view来渲染视图
 */
class Model {

    /**
     * 缓存的键名
     * @var string 
     */
    public $key = '';

    /**
     * 自定义键名的TAG
     * @var string 
     */
    public $diynamekey = '';

    /**
     * 所有已读取的条目,注意数据是无序的
     * @var array 
     */
    protected $entries = array();
    protected $diynameentries = array();

    /**
     * 是否支持Redis Hash缓存数据
     * @var boolean 
     */
    protected $isredis = FALSE;

    /**
     * 是否已加载全部数据
     * @var boolean 
     */
    protected $loaded = FALSE;

    /**
     * 构造函数
     */
    public function __construct() {
        $this->isredis = Cache::options('driver') == 'redis' ? TRUE : FALSE;
        //如果设置了键名,且对应的hash缓存不存在,则更新存入缓存
        if ($this->key) {
            if (!$this->cache->exist($this->key)) {
                $result = array();
                $diynameresult = array();
                $this->db->query('SELECT * FROM {pre}' . $this->key);
                while ($row = $this->db->fetch()) {
                    $result[$row['id']] = $row;
                    if ($this->diynamekey) {
                        $diynameresult[$row['diyname']] = $row['id'];
                    }
                }
                if ($result) {
                    if (!$this->isredis) {
                        $this->cache->set($this->key, $result);
                        $this->entries = $result;
                    } else {
                        $this->redis->hMset($this->key, $result);
                    }
                }
                if ($this->diynamekey && $diynameresult) {
                    $this->cache->set($this->diynamekey, $diynameresult);
                    if (!$this->isredis) {
                        $this->diynameentries = $diynameresult;
                    } else {
                        $this->redis->hMset($this->diynamekey, $diynameresult);
                    }
                }
            } else {
                //如果不支持Redis Hash缓存的情况下直接取出所有缓存数据
                if (Cache::options('driver') != 'redis') {
                    $this->entries = $this->cache->get($this->key);

                    if ($this->diynamekey) {
                        $this->diynameentries = $this->cache->get($this->diynamekey);
                    }
                    $this->loaded = TRUE;
                }
            }
        }
    }

    /**
     * 属性读取魔术方法
     * 
     * 当读取一个不存在的属性时,如果该属性在注册空间中有存在则读取注册空间的值
     * @param string $name 对象名称
     * @return object
     */
    public function __get($name) {
        if (Yaf_Registry::has($name)) {
            return Yaf_Registry::get($name);
        }
    }

    /**
     * 读取指定条目信息
     * @param string $id 条目ID
     * @return array
     */
    public function get($id) {
        if (isset($this->entries[$id])) {
            return $this->entries[$id];
        }
        if ($this->isredis) {
            $this->entries[$id] = $this->redis->hGet($this->key, $id) ? : array();
        }
        return $this->entries[$id];
    }

    /**
     * 读取所有条目信息,谨慎使用
     */
    public function all() {
        if ($this->loaded) {
            return $this->entries;
        }
        if ($this->isredis) {
            $this->entries = $this->redis->hGetAll($this->key);
        }
        $this->loaded = TRUE;
        return $this->entries;
    }

    /**
     * 读取所有条目ID集合
     * @return array
     */
    public function ids() {
        if ($this->isredis) {
            return $this->redis->hKeys($this->key);
        } else {
            return array_keys($this->entries);
        }
    }

    /**
     * 批量读取指定条目ID集合的信息
     * @param array $ids 条目ID集合
     * @return array
     */
    public function multi($ids = array()) {
        if (!$ids)
            return array();
        $ids = is_array($ids) ? $ids : explode(',', $ids);

        $alllist = array();
        $multilist = array();
        $multi_ids = array();
        foreach ($ids as $k => $v) {
            if (isset($this->entries[$v])) {
                $alllist[$v] = $this->entries[$v];
            } else {
                $multi_ids[] = $v;
            }
        }
        if ($this->isredis) {
            if ($multi_ids) {
                $multilist = $this->redis->hMGet($this->key, $multi_ids);
                $multilist = $multilist ? $multilist : array();
            }
        }
        foreach ($multilist as $k => $v) {
            $alllist[$k] = $v;
        }
        $alllist = array_filter($alllist);
        return $alllist;
    }

    /**
     * 通过自定义名称获取数据
     * @param string $name
     * @return array
     */
    public function diyname($name) {
        if (isset($this->diynameentries[$name]))
            return $this->diynameentries[$name];
        if ($this->isredis) {
            $id = $this->redis->hExists($this->diynamekey, $name) ? $this->redis->hGet($this->diynamekey, $name) : '';
        }
        return $this->get($id);
    }

}
